package cn.iocoder.mall.order.application.controller.users;

import cn.hutool.core.date.DateTime;
import cn.iocoder.common.framework.util.HttpUtil;
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.common.utils.common.api.vo.Result;
import cn.iocoder.common.utils.common.system.util.JwtUtil;
import cn.iocoder.common.utils.common.util.ObjectUtils;
import cn.iocoder.common.utils.common.util.json.JacksonUtils;
import cn.iocoder.mall.admin.api.DataDictService;
import cn.iocoder.mall.admin.api.bo.datadict.DataDictBO;
import cn.iocoder.mall.order.api.CartService;
import cn.iocoder.mall.order.api.OrderService;
import cn.iocoder.mall.order.api.bo.*;
import cn.iocoder.mall.order.api.constant.DictKeyConstants;
import cn.iocoder.mall.order.api.constant.OrderErrorCodeEnum;
import cn.iocoder.mall.order.api.constant.OrderStatusEnum;
import cn.iocoder.mall.order.api.dto.*;
import cn.iocoder.mall.order.application.convert.CartConvert;
import cn.iocoder.mall.order.application.convert.OrderConvertAPP;
import cn.iocoder.mall.order.application.po.user.OrderCreatePO;
import cn.iocoder.mall.order.application.vo.*;
import cn.iocoder.mall.order.biz.dataobject.OrderCancelDO;
import cn.iocoder.mall.order.biz.dataobject.OrderDO;
import cn.iocoder.mall.product.api.ProductSpuService;
import cn.iocoder.mall.product.api.bo.*;
import cn.iocoder.mall.promotion.api.CouponService;
import cn.iocoder.mall.promotion.api.bo.CouponCardAvailableBO;
import cn.iocoder.mall.promotion.api.bo.CouponCardDetailBO;
import cn.iocoder.mall.shop.api.ShopClerkRelationShipService;
import cn.iocoder.mall.shop.api.ShopService;
import cn.iocoder.mall.shop.api.pojo.ShopDTO;
import cn.iocoder.mall.user.sdk.annotation.RequiresLogin;
import cn.iocoder.mall.user.sdk.context.UserSecurityContextHolder;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.sql.Date;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.common.framework.vo.CommonResult.success;

/**
 * 订单API(users)
 *
 * @author Sin
 * @time 2019-03-24 11:24
 */
@RestController
@RequestMapping("user/order")
@Api(description = "用户订单") // TODO FROM 芋艿 to 小范，description 已经废弃啦
public class OrderController {

    @Reference(validation = "true", version = "${dubbo.provider.OrderService.version}")
    private OrderService orderService;

    @Reference(validation = "true", version = "${dubbo.provider.CartService.version}")
    private CartService cartService;

    @Reference(validation = "true", version = "${dubbo.consumer.DataDictService.version}")
    private DataDictService dataDictService;

    @Reference(validation = "true", version = "${dubbo.consumer.CouponService.version}")
    private CouponService couponService;

    @Reference(validation = "true", version = "${dubbo.consumer.ProductSpuService.version}")
    private ProductSpuService productSpuService;

    @Reference(validation = "true", version = "${dubbo.consumer.ShopClerkRelationShipService.version}")
    private ShopClerkRelationShipService relationShipService;
    @Reference(validation = "true", version = "${dubbo.consumer.ShopService.version}")
    private ShopService shopService;

    @GetMapping("/list")
    @RequiresLogin
    @ApiOperation("订单分页")
    public CommonResult<OrderPageBO> getOrderPage(@Validated OrderQueryDTO orderQueryDTO) {
        String userId = JwtUtil.getUserIdByToken();
        orderQueryDTO.setUserId(userId);
        return orderService.getOrderPage(orderQueryDTO);
    }

    @PostMapping("/createOrder")
    @RequiresLogin
    @ApiOperation("创建订单")
    public CommonResult<OrderCreateBO> createOrder(@RequestBody @Validated OrderCreatePO orderCreatePO,
                                                   HttpServletRequest request) {
        String userId =JwtUtil.getUserIdByToken();
        OrderCreateDTO orderCreateDTO = OrderConvertAPP.INSTANCE.convert(orderCreatePO);
        orderCreateDTO.setUserId(userId).setIp(HttpUtil.getIp(request));
        return orderService.createOrder(orderCreateDTO);
    }


    @PostMapping("/createOrderFromCart")
    @RequiresLogin
    @ApiOperation("创建订单购物车")
    public CommonResult<OrderCreateBO> createOrderFromCart(@RequestBody CreateOrderParamsVO vo,

                                                           HttpServletRequest request) {
        String userId = JwtUtil.getUserIdByToken();
        // 获得购物车中选中的商品

        List<CartItemBO> cartItems = cartService.list(userId, true);
        Set<String> shopId=cartItems.stream().collect(Collectors.groupingBy(CartItemBO::getShopId)).keySet();
        if(shopId.size()>1){
            return CommonResult.error("仅允许一次提交一个商店的商品");
        }
        if (cartItems.isEmpty()) {
            return ServiceExceptionUtil.error(OrderErrorCodeEnum.ORDER_CREATE_CART_IS_EMPTY.getCode());
        }
        // 创建 OrderCreateDTO 对象
        OrderCreateDTO orderCreateDTO = OrderConvertAPP.INSTANCE.createOrderCreateDTO(userId, vo.getUserAddressId(),
                vo.getRemark(), HttpUtil.getIp(request),
                cartItems, vo.getCouponCardId());
        orderCreateDTO.setShopId(shopId.iterator().hasNext()?shopId.iterator().next():"");
        // 创建订单
        CommonResult<OrderCreateBO> createResult = orderService.createOrder(orderCreateDTO);
        if (createResult.isError()) {
            return CommonResult.error(createResult);
        }
        // 清空购物车 // TODO 芋艿，需要标记删除的原因，即结果为创建为某个订单。
        cartService.deleteList(userId, cartItems.stream().map(CartItemBO::getSkuId).collect(Collectors.toList()));
        // 返回结果
        return createResult;
    }

    @GetMapping("/confirmCreateOrder")
    @RequiresLogin
    @ApiOperation("确认创建订单")
    public CommonResult<UsersOrderConfirmCreateVO> getConfirmCreateOrder(@RequestParam("skuId") Long skuId,
                                                                         @RequestParam("quantity") Integer quantity,
                                                                         @RequestParam(value = "couponCardId", required = false) Integer couponCardId) {
        String userId =JwtUtil.getUserIdByToken();


        // 创建 CalcOrderPriceDTO 对象，并执行价格计算
        CalcOrderPriceDTO calcOrderPriceDTO = new CalcOrderPriceDTO()
                .setUserId(userId)
                .setItems(Collections.singletonList(new CalcOrderPriceDTO.Item(skuId, quantity, true)))
                .setCouponCardId(couponCardId);
        CalcOrderPriceBO calcOrderPrice = cartService.calcOrderPrice(calcOrderPriceDTO);
        List<Long> s=new ArrayList<>();
        s.add(skuId);

        // 获得优惠劵
        List<CouponCardAvailableBO> couponCards = couponService.getCouponCardList(userId,
                CartConvert.INSTANCE.convertList(calcOrderPrice.getItemGroups()));
        // 执行数据拼装
        UsersOrderConfirmCreateVO result= CartConvert.INSTANCE.convert(calcOrderPrice).setCouponCards(couponCards);

        return success(result);
    }

    @PostMapping("/confirm_receiving")
    @RequiresLogin
    @ApiOperation("确认收货")
    public CommonResult confirmReceiving(@RequestParam("orderId") Long orderId) {
        String userId ="";
        return orderService.confirmReceiving(userId, orderId);
    }

    @GetMapping("/info")
    @RequiresLogin
    @ApiOperation("订单详情")
    public CommonResult<OrderInfoBO> orderInfo(@RequestParam("orderId") Long orderId) {
        String userId =JwtUtil.getUserIdByToken();
        CommonResult<OrderInfoBO> commonResult = orderService.info(userId, orderId);

        OrderInfoBO orderInfoBO = commonResult.getData();
        if (orderInfoBO != null) {
            CommonResult<DataDictBO> dictResult = dataDictService
                    .getDataDict(DictKeyConstants.ORDER_STATUS, orderInfoBO.getStatus());
            orderInfoBO.setStatusText(dictResult.getData().getDisplayName());
        }
        return commonResult;
    }

    @PostMapping("/updatePaySuccess")
    public CommonResult updatePaySuccess(@RequestBody Map<String,Object> params){

        String orderIdParmas= (String) params.get("orderId");
        Long orderId=Long.parseLong(orderIdParmas);
        Integer payAmount= (Integer) params.get("payAmount");
        orderService.updatePaySuccess(orderId,payAmount);
        orderService.generatorOrderCredential(new OrderCredentialDTO().setOrderId(orderId).setPayTime(new Date(System.currentTimeMillis())));
        return CommonResult.ok();
    }

    @PostMapping("/getPersonalOrderCredential")
    public CommonResult getPersonalOrderCredential(@Valid  @RequestBody CredentialVerifyVo dto, BindingResult bindingResult){
        if (bindingResult.hasErrors()){
            return CommonResult.error(JacksonUtils.toJSONString(bindingResult.getAllErrors()));
        }
        dto.setUserId(JwtUtil.getUserIdByToken());
        CredentialVerifyDTO credentialVerifyDTO= new CredentialVerifyDTO();
        BeanUtils.copyProperties(dto,credentialVerifyDTO);
        return orderService.getPersonalOrderCredential(credentialVerifyDTO);
    }

    @PostMapping("/writeOffOrderCredential")
    public CommonResult writeOffOrderCredential(@RequestBody @Valid CreadentialSecrexVo credentialVerifyDTO, BindingResult bindingResult){

        if (bindingResult.hasErrors()){
            return CommonResult.error("请求参数错误");
        }

        return   orderService.writeOffOrderCredential(new WriteOffOrderCredentialDTO().setConsumeTime(new DateTime()).setOrderId(credentialVerifyDTO.getOrderId())
                .setIp(credentialVerifyDTO.getIMEI()).setSecretText(credentialVerifyDTO.getSecretText()).setSellerId(JwtUtil.getUserIdByToken()));
    }


    @GetMapping("/seller/getOrderListOfSeller")
    public CommonResult<OrderPageBO> getOrderListByShopId(@Validated OrderQueryDTO orderQueryDTO) {
        orderQueryDTO.setDeleted(0);
        CommonResult<List<ShopDTO>> commonResult=shopService.getListOfStores(JwtUtil.getUserIdByToken());
        if (!commonResult.isSuccess()||commonResult.getData().isEmpty()){
            throw ServiceExceptionUtil.exception(111,"该用户名下不存在商店");

        }
        orderQueryDTO.setShopIds(commonResult.getData().stream().map(ShopDTO::getId).collect(Collectors.toList()));
        return  orderService.getOrderPageByShopIds(orderQueryDTO);
    }

    @GetMapping("/seller/getOneOrderDetailsById")
    public CommonResult<OrderBO> getOneOrderDetailById(@RequestParam Long orderId){
       OrderBO orderBO= orderService.getOrderById(orderId);
        if (orderBO==null||OrderStatusEnum.ALREADY_SHIPMENT.getValue()!=orderBO.getStatus()){
            return CommonResult.error("未找到订单信息");
        }

            CommonResult result=relationShipService.sellerIsInShop(JwtUtil.getUserIdByToken(),orderBO.getShopId());
       if (!result.isSuccess()){
           return CommonResult.error("您无权限处理此订单");
       }
       return CommonResult.success(orderBO);

    }

    @GetMapping("/seller/getOrderListOfClerk")
    public CommonResult<OrderPageBO> getOrderListOfClerk(@RequestParam Integer pageNo,@RequestParam Integer pageSize){
      return orderService.getOrderPageByClerkId(JwtUtil.getUserIdByToken(),pageNo,pageSize);
    }

    @GetMapping("/app/getOrderItemInfList")
    public  CommonResult<List<OrderItemInfoBO>> getOrderItemInfList(@RequestParam Long orderId){

        CommonResult<List<OrderItemBO>> result=orderService.getOrderItems(orderId);
        List<OrderItemInfoBO> list=result.getData().stream().map(orderItemBO -> {return ObjectUtils.copyObject(orderItemBO,OrderItemInfoBO.class);}).collect(Collectors.toList());
        if (result.isSuccess()&&result.getData()!=null){
            List<Long> ids=result.getData().stream().map(OrderItemBO::getSkuId).collect(Collectors.toList());
            List<SimpleSpuInfoBO> list1=productSpuService.getProductSpuListBySkuIds(ids);
            list1.stream().forEach(simpleSpuInfoBO->{list.stream().forEach(orderItemInfoBO ->{
                System.out.println(simpleSpuInfoBO.getSkuId()+"::::"+orderItemInfoBO.getSkuId());
                if (simpleSpuInfoBO.getSkuId().equals(orderItemInfoBO.getSkuId())){
                orderItemInfoBO.setSpuId(simpleSpuInfoBO.getId());
                orderItemInfoBO.setSpuName(simpleSpuInfoBO.getName());
            }} );});
        }

        return CommonResult.success(list);
    }

    @PostMapping("/cancelOrder")
    public CommonResult cancelOrder(@RequestBody @Valid OrderCancelVO cancelVO, BindingResult bindingResult){
        if (bindingResult.hasErrors()){
            return CommonResult.error("参数不全");
        }
        return orderService.cancelOrder(cancelVO.getOrderId(),cancelVO.getReason(),cancelVO.getOtherReason());
    }
}
